繼續做我的AI Side Project:「每拍呷-營養標示一拍就懂」
✔️今日進度1/14:確認營養標示算法、蒐集資料、統整國民健康署DIRS、把熱量&鈉&糖&脂肪換算成白飯&醬油&方糖&沙拉油、暫時先用GRADIO介面做初步的測試。
先看了家裡的零食,確認營養標示算法,我決定要先直接算吃完一整包的量,以後如果行有餘力,可以讓用戶選擇份量,譬如說吃了一包、半包、1/4包,或是秤克數。
每日鈉總攝取量不宜超過2400毫克(即6公克鹽=1茶匙鹽=2又2/5湯匙醬油)(1茶匙=5cc;1湯匙=15cc)
(算到這裡覺得好驚人喔!原來一天吃超過一茶匙鹽就爆表了,那很多人應該也是每天爆表)
添加糖攝取量不宜超過總熱量的10%(1顆方糖5公克),以總熱量1200大卡為例,10%則為120大卡,因為1克糖是產生4大卡熱量,故建議糖攝取量為30g,不能超過6顆方糖。
依據食藥署食品營養成分資料庫,1杯700毫升的「全糖」珍珠奶茶,含糖量近62公克,一天一杯就超過每日糖攝取上限。
脂肪每日建議攝取量上限是男性70公克與女性55公克、飽和脂肪每日建議攝取量上限是男性23公克、女性18公克(男、女性分別以體重70、55公斤之靜態工作者估計),我先暫時算總脂肪就好。1份油脂=15粒開心果=1茶匙沙拉油5克。後續測試先參考女性靜態工作者的55克,之後會考慮將用戶的性別加入設定。
簡易食物代換:
一份主食=1/2碗熟麵條=1片吐司=白飯1/4碗(約40克70大卡);
一平碗的白飯約有160公克、熱量280大卡。
我覺得代換成白飯應該比麵條跟吐司更直覺,所以就決定是白飯了!
然後統一規格,數字都一律四捨五入到小數點後一位;
之後我還要放警語,類似「本分析結果僅供參考、如有醫療相關問題請諮詢醫院」之類的
import math
import gradio as gr
# --- 營養素常數與換算表 ---
NUTRITION_CONSTANTS = {
# 每日建議攝取量 (DRIs)
"DRIS": {
# 鈉:單位毫克(mg),以衛福部建議的2400mg為準
"SODIUM_UPPER_LIMIT_MG": 2400,
# 糖:單位公克(g),以1200大卡總熱量為例,10%熱量相當於30g糖
"SUGAR_UPPER_LIMIT_G": 30,
# 脂肪:單位公克(g),參考女性靜態工作者的55公克
"FAT_FEMALE_UPPER_LIMIT_G": 55,
},
# 食物代換與比喻
"CONVERSIONS": {
# 白飯:1平碗約160克,280大卡
"RICE_KCAL_PER_BOWL": 280,
# 鹽與醬油:2400mg鈉(6g鹽) = 2.4湯匙醬油,得出1湯匙醬油約含1000mg鈉
"SODIUM_MG_PER_TBS_SOY_SAUCE": 1000,
# 脂肪與沙拉油:1茶匙沙拉油5克脂肪
"FAT_G_PER_TSP_OIL": 5,
# 糖與方糖:1顆方糖5公克
"SUGAR_G_PER_CUBE": 5,
}
}
def analyze_and_report_nutrition(
serving_size_g_str: str, # 接收字串類型
servings_per_package_str: str, # 接收字串類型
sodium_per_serving_mg_str: str, # 接收字串類型
sugar_per_serving_g_str: str, # 接收字串類型
fat_per_serving_g_str: str, # 接收字串類型
calories_per_serving_kcal_str: str # 接收字串類型
) -> str:
"""
根據單份營養標示和總份數,計算並生成完整的營養報告,並使用表情符號。
Args:
serving_size_g_str: 每一份的克數 (字串)。
servings_per_package_str: 本包裝含幾份 (字串)。
sodium_per_serving_mg_str: 每一份含的鈉(毫克,字串)。
sugar_per_serving_g_str: 每一份含的糖(公克,字串)。
fat_per_serving_g_str: 每一份含的脂肪(公克,字串)。
calories_per_serving_kcal_str: 每一份含的熱量(大卡,字串)。
Returns:
一個包含所有計算結果和建議的文字回覆。
"""
try:
# 將字串輸入轉換為浮點數
serving_size_g = float(serving_size_g_str)
servings_per_package = float(servings_per_package_str)
sodium_per_serving_mg = float(sodium_per_serving_mg_str)
sugar_per_serving_g = float(sugar_per_serving_g_str)
fat_per_serving_g = float(fat_per_serving_g_str)
calories_per_serving_kcal = float(calories_per_serving_kcal_str)
except ValueError:
return "### 輸入錯誤:請確認您輸入的都是有效的數字喔!" # 錯誤訊息也放大字體
except Exception as e:
return f"### 發生未知錯誤:{e}" # 錯誤訊息也放大字體
然後是計算是否有超過一天攝取量限制的部份,分成鈉、糖、脂肪三項,如果超過100%就回覆攝取已爆表:
# 加入警示判斷
warnings = []
if sodium_percentage > 100:
warnings.append("⚠️ **注意:鈉攝取已爆表!**")
if sugar_percentage > 100:
warnings.append("⚠️ **注意:糖攝取已爆表!**")
if fat_percentage > 100:
warnings.append("⚠️ **注意:脂肪攝取已爆表!**")
if warnings:
message_parts.append("\n" + "\n".join(warnings))
用emoji加紅綠燈來表示,預設為😊笑臉。
如果任一營養素超過100%,則會變成😡生氣臉。
如果沒有生氣臉的情況,但有任一營養素介於**75%到100%**之間,則會變成😟哭臉。
營養素超過100%的警示使用⚠️。
介於75%到100%的提醒,使用對應的食物符號(鈉🧂-->鹽罐,糖🍬-->糖果,脂肪🧈-->奶油塊)。
明日進度:
因為今天提前做了明天原本要做的紅綠燈分類,明天改成針對成分表裡的食品添加物作分類,初步分類成:香料、防腐劑、乳化劑、色素、其他,用戶輸入文字內容後,可收到圓餅圖或其他視覺化分析內容。
加油!!